/**
 * Copyright (c) 2019 xstgongyi.org
 * All rights reserved.
 */
package org.xstgongyi.eduaid.controller;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;
import org.xstgongyi.eduaid.common.ControllerHelper;
import org.xstgongyi.eduaid.dataobject.ProjectDO;
import org.xstgongyi.eduaid.dataobject.SemesterDO;
import org.xstgongyi.eduaid.dataobject.StudentAidDO;
import org.xstgongyi.eduaid.dataobject.StudentDO;
import org.xstgongyi.eduaid.service.*;

import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.*;

/**
 * @author oldcrane<br   />
 * @created 2019-04-24
 */
@Controller
@RequestMapping("/students-aids")
public class StudentAidController {

    private static final int DEFAULT_PAGE = 1;
    private static final int DEFAULT_SIZE = 20;

    @Autowired
    private StudentAidService aidService;

    @Autowired
    private StudentService studentService;

    @Autowired
    private SponsorService sponsorService;

    @Autowired
    private VolunteerService volunteerService;

    @Autowired
    private ProjectService projectService;

    @Autowired
    private SemesterService semesterService;

    @Autowired
    private GradeService gradeService;

    @Autowired
    private StudentAidStatisticsService aidStatService;

    @Autowired
    private StudentAidExportService aidExportStatus;

    @GetMapping("/overall")
    public String page_list_overall() {
        return "aid/aid_list_overall";
    }

    @RequestMapping(value = "/extend_from_prev_semester", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, Object> extend_from_prev_semester(
            @RequestParam(name = "projectId", defaultValue = "0") Integer projectId,
            @RequestParam(name = "semesterId", defaultValue = "0") Integer semesterId) {
        if (projectId <= 0 || semesterId <= 0) {
            ControllerHelper.errorResponse(1, "必须指定项目和学期，才能执行本操作。");
        }

        int rowNum = aidService.extendAid(projectId, semesterId);
        return ControllerHelper.successResponse(null, rowNum + " 名学生的资助信息已被延长。");
    }

    @GetMapping("/unextended")
    @ResponseBody
    public Map<String, Object> list_unextended_student(
            @RequestParam(name = "projectId", defaultValue = "0") Integer projectId,
            @RequestParam(name = "semesterId", defaultValue = "0") Integer semesterId) {

        List<StudentDO> studentList = aidService.listUnextendedStudent(projectId, semesterId);

        // 转换为展示处理需要的格式。此类逻辑准备以后移动到展示层。TODO Crane 2019-08-15
        List<Map<String, Object>> result = new ArrayList<>();
        for (StudentDO student : studentList) {
            Map<String, Object> item = new HashMap<>();
            item.put("id", student.getId());
            item.put("name", student.getName() + "(" + student.getSn() + ")");
            result.add(item);
        }

        return ControllerHelper.successResponse(result);
    }

    @RequestMapping(value = "/statistics_page")
    public String statistics(@RequestParam(name = "projectId", defaultValue = "0") Integer projectId, ModelMap map) {
        List<ProjectDO> projectList = projectService.listAll();
        map.put("projects", projectList);
        map.put("projectId", projectId);

        List<StudentAidStatisticsDTO> aidStatList = aidStatService.calcStatisticsOfOngoingPhases(projectId);
        map.put("aidStatList", aidStatList);
        return "aid/aid_statistics";
    }

    @GetMapping("")
    @ResponseBody
    public Map<String, Object> list_get(StudentAidListParamDTO params) {
        return list_post(params);
    }

    @PostMapping("/search")
    @ResponseBody
    public Map<String, Object> list_post(@RequestBody StudentAidListParamDTO params) {

        // 处理翻页参数
        if (null == params.getPage()) {
            params.setPage(DEFAULT_PAGE);
        }
        if (null == params.getLimit()) {
            params.setLimit(DEFAULT_SIZE);
        }

        Map<String, Object> result = new HashMap<>();
        List<StudentAidDTO> rows = new ArrayList<>();

        int total = aidService.countTotal(params);
        params.setTotal(total);
        if (total > 0) {
            List<StudentAidDO> aids = aidService.listPage(params);
            for (StudentAidDO aid : aids) {
                StudentAidDTO vo = StudentAidDTO.of(aid);
                vo.setStudentInfo(studentService.getStudentById(aid.getStudentId()));
                vo.setSponsorInfo(sponsorService.getById(aid.getSponsorId()));
                vo.setVolunteerInfo(volunteerService.getById(vo.getVolunteerId()));
                vo.setProjectInfo(projectService.getById(aid.getProjectId()));
                vo.setSemesterInfo(semesterService.getById(aid.getSemesterId()));
                vo.setGradeInfo(gradeService.getById(aid.getGradeId()));
                rows.add(vo);
            }
        }
        result.put("page", params.getPage());
        result.put("total", total);
        result.put("rows", rows);
        return ControllerHelper.successResponse(result);
    }

    @PostMapping("/{id}")
    @ResponseBody
    public Map<String, Object> updateAidRecord(@PathVariable("id") Integer id, @RequestBody StudentAidDTO dto) {
        dto.setId(id);
        aidService.updateAidTraceInfo(dto);
        return ControllerHelper.successResponse(null);
    }

    @PostMapping("")
    @ResponseBody
    public Map<String, Object> addAidRecord(@RequestBody StudentAidDTO dto) {
        int num = aidService.insertAidForExistingStudent(dto);
        if (num > 0) {
            return ControllerHelper.successResponse(null, "已创建新的助学记录");
        } else {
            return ControllerHelper.errorResponse(1, "未创建新的助学记录，请刷新页面后检查该学生在你指定的学期是否已存在助学记录");
        }
    }

    @GetMapping("/export")
    public ResponseEntity<byte[]> export(@RequestParam(name = "projectId", defaultValue = "0") Integer projectId,
                                         @RequestParam(name = "semesterId", defaultValue = "0") Integer semesterId,
                                         @RequestParam(name = "options") String optionParam)
            throws java.io.IOException {

        ProjectDO project = projectService.getById(projectId);
        if (null == project) {
            return errorResponse(0 <= projectId ? "请指定项目" : "指定的项目不存在");
        }
        SemesterDO semester = semesterService.getById(semesterId);
        if (null == semester) {
            return errorResponse(0 <= semesterId ? "请指定学期" : "指定的学期不存在");
        }

        String filename = project.getName() + "-" + semester.getName() + ".xls";

        // xls format
        HttpHeaders headers = new HttpHeaders();
        headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
        headers.add("Pragma", "no-cache");
        headers.add("Expires", "0");
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        try {
            headers.setContentDispositionFormData("attachment", URLEncoder.encode(filename, "UTF-8"));
        } catch (UnsupportedEncodingException e) {
            headers.setContentDispositionFormData("attachment", projectId + "-" + semesterId + ".xls");
        }

        String[] options = null == optionParam ? new String[0] : optionParam.split(",");
        Set<String> optionSet = new HashSet<>();
        for (String option : options) {
            if (!option.trim().isEmpty()) {
                optionSet.add(option.trim().toUpperCase());
            }
        }
        HSSFWorkbook workbook = aidExportStatus.expoertAidsToExcel(projectId, semesterId, optionSet);
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        workbook.write(outStream);
        return new ResponseEntity<byte[]>(outStream.toByteArray(), headers, HttpStatus.OK);
    }

    private ResponseEntity<byte[]> errorResponse(String message) {
        HttpHeaders headers = new HttpHeaders();
        headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
        headers.add("Pragma", "no-cache");
        headers.add("Expires", "0");
        headers.setContentType(MediaType.TEXT_PLAIN);
        return ResponseEntity.status(404).headers(headers).body(message.getBytes());
    }

    @RequestMapping(value = "/batch_update", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, Object> batch_update(@RequestParam(name = "aidIds") int[] aidIds,
                                            @RequestParam(name = "action") String action) {
        if (null == aidIds || null == action) {
            return ControllerHelper.successResponse(null, "no row updated");
        }

        aidService.batchUpdate(aidIds, action);

        return ControllerHelper.successResponse(null, "success");
    }

}
